import os, sys

PINFRAC_ROOT = os.environ.get("PINFRAC_ROOT", "~/.pinfrac")
PINFRAC_USERDATA = os.environ.get("PINFRAC_USERDATA", PINFRAC_ROOT + "/_userdata") + "/data.json"

from argparse import ArgumentParser
from pprint import pformat
import os
import json
from argparse import ArgumentParser


_raw_print = print
print = None


def _read_userdata(path=PINFRAC_USERDATA):
    try:
        with open(path, "r") as fp:
            data:dict = json.load(fp)
    except FileNotFoundError:
        data = dict()
    return data


def _write_userdata(data, path=PINFRAC_USERDATA):

    with open(path, "w") as fp:
        json.dump(data, fp, indent=4)


def _shell_print(s):
    format = str(s)
    _raw_print(f'printf "{format}\\n";')


def _shell_exec(cmd):
    _raw_print(f'{cmd};')


def status(data):
    _shell_print(pformat(data))


def rwdata(data, *argv):
    argp = ArgumentParser()
    argp.add_argument("--default", type=eval, default=None)
    argp.add_argument("--delete", action="store_true")
    argp.add_argument("key", type=str)
    argp.add_argument("value", type=eval, nargs="?", default=None)
    args = argp.parse_args(argv)

    # get
    if args.delete == False and args.value is None:
        _shell_print(data.get(args.key, args.default))
        exit(0)
        
    # set
    if args.delete == False and args.value is not None:
        data[args.key] = args.value
        
    # delete
    if args.delete:
        data.pop(args.key)


def is_package(package):
    return not package.startswith("_") and not package.startswith(".") and os.path.isdir(f"{PINFRAC_ROOT}/{package}")


def enable(data, package):
    if is_package(package):
        rwdata(data, f"{package}_enabled", "True")
        _shell_exec(f"source {PINFRAC_ROOT}/{package}/enable.sh")
        _shell_print(f"{package} enabled")
    else:
        _shell_print(f"{package} is not a package")


def disable(data, package):
    if is_package(package):
        rwdata(data, f"{package}_enabled", "False")
        _shell_exec(f"source {PINFRAC_ROOT}/{package}/disable.sh")
        _shell_print(f"{package} disabled")
    else:
        _shell_print(f"{package} is not a package")


def update(data):
    ...


def init(data):
    for package in os.listdir(PINFRAC_ROOT):
        if is_package(package) and data.get(f"{package}_enabled", False):
            _shell_exec(f"source {PINFRAC_ROOT}/{package}/enable.sh")


def route():
    ALL_COMMANDS = [
        "status", "enable", "disable", "update", "init", "rwdata"
    ]
    usage_msg = f"Usage: pinfrac [{'|'.join(ALL_COMMANDS)}]"
    if len(sys.argv) == 1 or sys.argv[1] not in ALL_COMMANDS:
        _shell_print(usage_msg)
        exit(1)
    data = _read_userdata()
    eval(sys.argv[1])(data, *sys.argv[2:])
    _write_userdata(data)


if __name__ == "__main__":
    try:
        route()
    except Exception as e:
        _shell_print(e)
